package net.heri.xmppchat.xmppclient;

import net.heri.xmppchat.util.ChatConstant;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Type;

import android.content.SharedPreferences;
import android.util.Log;

import com.google.inject.Inject;
import com.google.inject.Singleton;

@Singleton
public class XmppClient implements IXmppClient {

	private final String TAG = XmppClient.class.getSimpleName();
	private static final int packetReplyTimeout = 500; // millis
	private String server;
	private int port;

	private ConnectionConfiguration config;
	private XMPPConnection connection;

	private ChatManager chatManager;
	private MessageListener messageListener;

	@Inject
	public XmppClient(SharedPreferences preferences) {
		this.server = preferences.getString(ChatConstant.Reference.HOST, "127.0.0.1");
		this.port = preferences.getInt(ChatConstant.Reference.PORT, 5222);
	}

	@Override
	public void init(MessageListener listener) throws XMPPException {

		Log.i(TAG, String.format("Initializing connection to server %1$s port %2$d", server, port));

		SmackConfiguration.setPacketReplyTimeout(packetReplyTimeout);

		config = new ConnectionConfiguration(server, port);
		config.setSASLAuthenticationEnabled(false);
		config.setSecurityMode(SecurityMode.disabled);

		connection = new XMPPConnection(config);
		connection.connect();

		Log.i(TAG, "Connected: " + connection.isConnected());

		chatManager = connection.getChatManager();
		messageListener = listener;
	}

	@Override
	public void setStatus(boolean available, String status) {

		Presence.Type type = available ? Type.available : Type.unavailable;
		Presence presence = new Presence(type);

		presence.setStatus(status);
		connection.sendPacket(presence);

	}

	public void requestCreateEntry(String user, String name) throws Exception {
		Log.i(TAG, String.format(
				"Creating entry for buddy '%1$s' with name %2$s", user, name));
		Roster roster = connection.getRoster();
		roster.createEntry(user, name, null);
	}

	@Override
	public void login(String username, String password) throws XMPPException {
		if (connection != null && connection.isConnected()) {
			connection.login(username, password);
		}
	}

	@Override
	public void logout() {
		if (connection != null && connection.isConnected()) {
			connection.disconnect();
		}
	}

	@Override
	public void sendMessage(String body, String remoteUsername)
			throws XMPPException {
		Log.i(TAG, String.format("Sending mesage '%1$s' to user %2$s", body, remoteUsername));
		Chat chat = chatManager.createChat(remoteUsername, messageListener);
		chat.sendMessage(body);
	}

}
